dashdashHARD

dashdashHARD

Exploring the depths of render.com

Non-prod Environment Management

web service environments

Are you tired of the arguing back and forth with your QA team that the staging environment is broken again? Or that the data in your database needs to be flushed because of a botched migration? Persistent, non-prod environments are so useful, but can be an immense, thankless, maintenance burden.

Is there an easy way to manage them? Ideally, you have so much automation developers don’t get brought in to deal with the cruft and fragility of non-prod environments and the noise and headache they create as a result. As well, we all want tooling to exist and be available, so that we don’t have to spend cycles creating and maintaining our own tools to fix specific problems.

Render has some useful out of the box solutions that help with non-prod environment management that really reduces the technical lift required to fix common problems. Let’s examine some of them.

Turnkey Environments and Separation of Config and Code

A blueprint spec (aka a render.yaml) is a definition of an environment. One understated feature of the blueprint is that it can reference resources outside the repo in which it’s declared.

You can create a render.yaml in a repo that is totally separate from your code and lay out your configuration there by defining the environment variables directly and/or referencing an environment group. In that render.yaml you’ll state which repo and branch render should deploy- and that can be a totally different repo from the one the render.yaml lives in.

For example:

This render.yaml lives in the repo https://github.com/dashdashhard/app-staging.git on branch main to define a staging environment:

services:  
  - type: web  
    name: app
    repo: https://github.com/dashdashhard/app.git
    branch: staging
    envVars:
      - fromGroup: staging-config
    autoDeploy: true

And a second, production environment defined by a render.yaml living in repo https://github.com/dashdashhard/app-prod.git on branch main:

services:  
  - type: web  
    name: app
    repo: https://github.com/dashdashhard/app.git
    branch: production
    envVars:
      - fromGroup: production-config
    autoDeploy: false

These two environments reference different branches in the same repo. Both environments have their own configuration, pulled from their own environment groups. Plus, with autoDeploy, the staging environment will automatically redeploy itself whenever the staging branch is updated.

Preview Environments

Render gives us the ability to spin up new environments per pull request- letting us test our code changes, database migrations, whatever we need in a throwaway environment.

Let’s say you have a persistent dev environment declared like this:

previewsEnabled: true
 services:  
  - type: web  
    name: app
    repo: https://github.com/dashdashhard/app.git
    branch: dev
    envVars:
      - fromGroup: dev-config
    autoDeploy: true

Note that previewsEnabled is set to true.

Whenever a PR is raised to merge into the branch that the persistent environment is hooked to (in our case, dev), a preview environment is created based on dev’s render.yaml for that PR. You have the ability to specify an initialization script for the database state- so you could load a database fixture file, or to load a dump from another environment. You have the tools to initialize your preview environments with whatever data and configuration is relevant for your testing, protecting the persistent dev environment from incomplete and unmerged changes.

As you add commits to your PR, your preview environment is redeployed automatically with your changes, and destroyed once the PR the environment is created from is merged.

Point in Time Recovery

We have all had database migration scripts fail (and if you haven’t yet, get ready because it’s coming).

If you do manage to, for example, merge a database migration that really messes up your persistent environment’s data, you can always perform a point in time recovery of your database to just before the merge happened while you revert the commit, or merge a fix for it. No more blame games- just a revert and restore and you’re back up and running. This is such an undervalued feature for environment management- it saves us tons of time since we dont have to figure out how to undo the damage, we just restore to a point in time before the damage was done.